<?php

declare(strict_types=1);

namespace app\admin\controller;

use app\common\AdminController;
use app\admin\validate\User as UserValidate;
use app\admin\model\User as UserDB;
use app\service\Encryptor;
use app\service\RedisSet;
use think\Request;

class UserAdmin extends AdminController
{
  protected $field = ['id', 'user_id as Id', 'avatar', 'user_name', 'nickname', 'phone_number', 'sex', 'status', 'login_ip','login_address', 'login_time', 'create_time', 'update_time'];
  protected $allowField = ['avatar', 'nickname', 'phone_number', 'sex', 'status'];
  protected function initialize()
  {
    $this->model = new UserDB();
  }
  public function list(array $rule = [], array $field = [], array $association = [], array $hidden = [])
  {
    $rule = [
      "userName" => [
        "mode" => "like",
        "field" => "user_name",
      ],
      "nickname" => [
        "mode" => "like",
        "field" => "nickname",
      ],
      "status" => [
        "mode" => "="
      ],
      "sex" => [
        "mode" => "="
      ],
      "createTime" => [
        "mode" => "between",
        "field" => "create_time",
      ],
    ];
    $association = [
      'role' => [
        'field' => 'id,role_key,role_name'
      ]
    ];
    return parent::list($rule, $this->field, $association, ['role.pivot','id']);
  }

  public function add(array $allowField = [], array $association = [], $data = [], $returnId = false)
  {
    $datas = input('post.');
    $data['user_name'] = $datas['userName'];
    $data['phone_number'] = $datas['phoneNumber'];
    try {
      Validate(UserValidate::class)->scene('edit')->check($data);
    } catch (\Throwable $th) {
      // throw $th;
      return error($th->getMessage());
    }
    $password = $datas['password'] ? Encryptor::decrypt($datas['password']) : '123456';
    $data['user_password'] = password_hash($password, PASSWORD_BCRYPT);
    $allowField = $this->allowField;
    $allowField[] = 'create_time';
    $allowField[] = 'create_by';
    $allowField[] = 'user_id';
    $allowField[] = 'user_name';
    $allowField[] = 'user_password';
    $microtime = microtime(true);
    $random = rand(100000, 999999);
    $data['user_id'] = floor($microtime * 1000) . $random;
    $association = [
      'role' => [
        'save' => $datas['role']
      ]
    ];
    return parent::add($allowField, $association, $data);
  }

  public function update(array $allowField = [], array $where = [], array $association = [], $data = [])
  {
    $datas = input('post.');
    $data['phone_number'] = $datas['phoneNumber'];
    try {
      Validate([
        'phone_number' => 'require|max:11|unique:user,phone_number,' . $datas['id'] . ',user_id',
      ])->message([
            'phone_number.require' => '手机号不能为空',
            'phone_number.max' => '手机号不能超过11个字符',
            'phone_number.unique' => '手机号已存在',
          ])->check($data);
    } catch (\Throwable $th) {
      // throw $th;
      return error($th->getMessage());
    }
    $allowField = $this->allowField;
    $allowField[] = 'update_time';
    $allowField[] = 'update_by';
    $allowField[] = 'user_password';
    $where = [['user_id', '=', $datas['id']]];
    $newRoles = $datas['role'];
    $user = $this->model->where($where)->find();
    $currentRoles = $user->role()->column('id');
    $oPassword = !empty($datas['oPassword']) ? Encryptor::decrypt($datas['oPassword']) : '';
    if (!password_verify($oPassword, $user->user_password)) {
      return error("密码错误");
    } else if (in_array($this->adminRoleId, $currentRoles)) {
      return error("修改失败，管理员不可修改");
    }
    if (count($newRoles) === count($newRoles, COUNT_RECURSIVE)) {
      $password = !empty($datas['password']) ? Encryptor::decrypt($datas['password']) : $oPassword;
      $data['user_password'] = password_hash($password, PASSWORD_BCRYPT);
      $rolesToAdd = array_diff($newRoles, $currentRoles);
      $rolesToRemove = array_diff($currentRoles, $newRoles);
      $association =empty($rolesToAdd) && empty($rolesToRemove) ? [] : [
        'role' => [
          'save' => $rolesToAdd,
          'remove' => $rolesToRemove
        ]
      ];
    }
    $res =  parent::update($allowField, $where, $association, $data);
    $dataRes = $res instanceof \think\response\Json ? $res->getData() : [];
    if ($dataRes['code'] == 200) {
      RedisSet::logoutById($this->model,  $datas['id'], $this->userId);
    }
    return $res;
  }

  public function del($ids, $type = false, $where = [])
  {
    $isId = explode(',', $ids);

    if ($this->isAdmin($isId)) {
      return error("删除失败，有管理员角色的用户不能删除");
    }
    return parent::del($ids, false, [['user_id', 'in', $ids]]);
  }

  protected function isAdmin($ids)
  {
    $hasAdmin = $this->model
      ->where([['user_id', 'in', $ids]])
      ->whereExists(function ($q) {
        $q->table('xl_user_role')
          ->whereRaw('xl_user_role.user_id = xl_user.id')
          ->where('role_id', $this->adminRoleId);
      })->select();
    return count($hasAdmin);
  }

  public function get($id, array $field = [], array $where = [], array $association = [], array $hidden = [])
  {
    $where = array_merge($where, ['user_id' => $id]);
    $association = [
      'role' => [
        'field' => 'id,role_key,role_name'
      ]
    ];
    return parent::get('', $this->field, $where, $association, ['role.pivot','id']);
  }
}
